using System.Collections.Generic;
using UnityEngine;

namespace PhysSound
{
	[AddComponentMenu("PhysSound/PhysSound Object")]
	public class PhysSoundObject : PhysSoundBase
	{
		public PhysSoundMaterial SoundMaterial;

		public bool AutoCreateSources;

		public bool PlayClipAtPoint;

		public AudioSource ImpactAudio;

		public List<PhysSoundAudioContainer> AudioContainers = new List<PhysSoundAudioContainer>();

		private float baseImpactVol;

		private float baseImpactPitch;

		private Dictionary<int, PhysSoundAudioContainer> _audioContainersDic;

		private Vector3 _prevVelocity;

		private bool _setPrevVelocity = true;

		private Vector3 _prevPosition;

		private Vector3 _kinematicVelocity;

		private Quaternion _prevRotation;

		private float _kinematicAngularVelocity;

		private Rigidbody _r;

		private Rigidbody2D _r2D;

		private Vector3 TotalKinematicVelocity => _kinematicVelocity + Vector3.one * _kinematicAngularVelocity;

		private void Start()
		{
			if (SoundMaterial == null)
			{
				return;
			}
			_r = GetComponent<Rigidbody>();
			_r2D = GetComponent<Rigidbody2D>();
			if (AutoCreateSources)
			{
				baseImpactVol = ImpactAudio.volume;
				baseImpactPitch = ImpactAudio.pitch;
				_audioContainersDic = new Dictionary<int, PhysSoundAudioContainer>();
				AudioContainers = new List<PhysSoundAudioContainer>();
				foreach (PhysSoundAudioSet audioSet in SoundMaterial.AudioSets)
				{
					if (!(audioSet.Slide == null))
					{
						PhysSoundAudioContainer physSoundAudioContainer = new PhysSoundAudioContainer(audioSet.Key);
						physSoundAudioContainer.SlideAudio = PhysSoundTempAudioPool.GetAudioSourceCopy(ImpactAudio, base.gameObject);
						physSoundAudioContainer.Initialize(SoundMaterial);
						_audioContainersDic.Add(physSoundAudioContainer.KeyIndex, physSoundAudioContainer);
						AudioContainers.Add(physSoundAudioContainer);
					}
				}
				ImpactAudio.loop = false;
			}
			else
			{
				if ((bool)ImpactAudio)
				{
					ImpactAudio.loop = false;
					baseImpactVol = ImpactAudio.volume;
					baseImpactPitch = ImpactAudio.pitch;
				}
				if (AudioContainers.Count > 0)
				{
					_audioContainersDic = new Dictionary<int, PhysSoundAudioContainer>();
					foreach (PhysSoundAudioContainer audioContainer in AudioContainers)
					{
						if (!SoundMaterial.HasAudioSet(audioContainer.KeyIndex))
						{
							UnityEngine.Debug.LogError("PhysSound Object " + base.gameObject.name + " has an audio container for an invalid Material Type! Select this object in the hierarchy to update its audio container list.");
						}
						else
						{
							audioContainer.Initialize(SoundMaterial);
							_audioContainersDic.Add(audioContainer.KeyIndex, audioContainer);
						}
					}
				}
			}
			if (PlayClipAtPoint)
			{
				PhysSoundTempAudioPool.Create();
			}
			else if (ImpactAudio != null && !ImpactAudio.isActiveAndEnabled)
			{
				ImpactAudio = PhysSoundTempAudioPool.GetAudioSourceCopy(ImpactAudio, base.gameObject);
			}
		}

		private void Update()
		{
			if (!(SoundMaterial == null))
			{
				for (int i = 0; i < AudioContainers.Count; i++)
				{
					AudioContainers[i].UpdateVolume();
				}
				if ((bool)ImpactAudio && !ImpactAudio.isPlaying)
				{
					ImpactAudio.Stop();
				}
				_kinematicVelocity = (base.transform.position - _prevPosition) / Time.deltaTime;
				_prevPosition = base.transform.position;
				_kinematicAngularVelocity = Quaternion.Angle(_prevRotation, base.transform.rotation) / Time.deltaTime / 45f;
				_prevRotation = base.transform.rotation;
			}
		}

		public void SetEnabled(bool enable)
		{
			if (enable && !base.enabled)
			{
				for (int i = 0; i < AudioContainers.Count; i++)
				{
					AudioContainers[i].Enable();
				}
				ImpactAudio.enabled = true;
				base.enabled = true;
			}
			else if (!enable && base.enabled)
			{
				if ((bool)ImpactAudio)
				{
					ImpactAudio.Stop();
					ImpactAudio.enabled = false;
				}
				for (int j = 0; j < AudioContainers.Count; j++)
				{
					AudioContainers[j].Disable();
				}
				base.enabled = false;
			}
		}

		public override PhysSoundMaterial GetPhysSoundMaterial(Vector3 contactPoint)
		{
			return SoundMaterial;
		}

		private void playImpactSound(GameObject otherObject, Vector3 relativeVelocity, Vector3 normal, Vector3 contactPoint)
		{
			if (SoundMaterial == null || !base.enabled || SoundMaterial.AudioSets.Count == 0 || !ImpactAudio)
			{
				return;
			}
			AudioClip impactAudio = SoundMaterial.GetImpactAudio(otherObject, relativeVelocity, normal, contactPoint);
			if (!impactAudio)
			{
				return;
			}
			float pitch = baseImpactPitch * SoundMaterial.GetScaleModPitch(base.transform.localScale) + SoundMaterial.GetRandomPitch();
			float num = baseImpactVol * SoundMaterial.GetScaleModVolume(base.transform.localScale) * SoundMaterial.GetImpactVolume(relativeVelocity, normal);
			if (PlayClipAtPoint)
			{
				PhysSoundTempAudioPool.Instance.PlayClip(impactAudio, base.transform.position, ImpactAudio, (!SoundMaterial.ScaleImpactVolume) ? ImpactAudio.volume : num, pitch);
				return;
			}
			ImpactAudio.pitch = pitch;
			if (SoundMaterial.ScaleImpactVolume)
			{
				ImpactAudio.volume = num;
			}
			ImpactAudio.clip = impactAudio;
			ImpactAudio.Play();
		}

		private void setSlideTargetVolumes(GameObject otherObject, Vector3 relativeVelocity, Vector3 normal, Vector3 contactPoint, bool exit)
		{
			if (SoundMaterial == null || !base.enabled || SoundMaterial.AudioSets.Count == 0)
			{
				return;
			}
			PhysSoundMaterial physSoundMaterial = null;
			PhysSoundBase component = otherObject.GetComponent<PhysSoundBase>();
			if ((bool)component)
			{
				if (component is PhysSoundTerrain)
				{
					PhysSoundTerrain physSoundTerrain = component as PhysSoundTerrain;
					Dictionary<int, PhysSoundComposition> composition = physSoundTerrain.GetComposition(contactPoint);
					foreach (PhysSoundAudioContainer value4 in _audioContainersDic.Values)
					{
						float mod = 0f;
						if (composition.TryGetValue(value4.KeyIndex, out PhysSoundComposition value))
						{
							mod = value.GetAverage();
						}
						value4.SetTargetVolumeAndPitch(base.gameObject, otherObject, relativeVelocity, normal, exit, mod);
					}
					return;
				}
				physSoundMaterial = component.GetPhysSoundMaterial(contactPoint);
			}
			PhysSoundAudioContainer value3;
			if ((bool)physSoundMaterial)
			{
				if (_audioContainersDic.TryGetValue(physSoundMaterial.MaterialTypeKey, out PhysSoundAudioContainer value2))
				{
					value2.SetTargetVolumeAndPitch(base.gameObject, otherObject, relativeVelocity, normal, exit);
				}
				else if (!SoundMaterial.HasAudioSet(physSoundMaterial.MaterialTypeKey) && SoundMaterial.FallbackTypeKey != -1 && _audioContainersDic.TryGetValue(SoundMaterial.FallbackTypeKey, out value2))
				{
					value2.SetTargetVolumeAndPitch(base.gameObject, otherObject, relativeVelocity, normal, exit);
				}
			}
			else if (SoundMaterial.FallbackTypeKey != -1 && _audioContainersDic.TryGetValue(SoundMaterial.FallbackTypeKey, out value3))
			{
				value3.SetTargetVolumeAndPitch(base.gameObject, otherObject, relativeVelocity, normal, exit);
			}
		}

		private void OnCollisionEnter(Collision c)
		{
			if (!(SoundMaterial == null) && base.enabled && SoundMaterial.AudioSets.Count != 0)
			{
				playImpactSound(c.collider.gameObject, c.relativeVelocity, c.contacts[0].normal, c.contacts[0].point);
				_setPrevVelocity = true;
			}
		}

		private void OnCollisionStay(Collision c)
		{
			if (!(SoundMaterial == null) && base.enabled && SoundMaterial.AudioSets.Count != 0 && _audioContainersDic != null)
			{
				if (_setPrevVelocity)
				{
					_prevVelocity = _r.velocity;
					_setPrevVelocity = false;
				}
				Vector3 relativeVelocity = _r.velocity - _prevVelocity;
				playImpactSound(c.collider.gameObject, relativeVelocity, c.contacts[0].normal, c.contacts[0].point);
				setSlideTargetVolumes(c.collider.gameObject, c.relativeVelocity, c.contacts[0].normal, c.contacts[0].point, exit: false);
				_prevVelocity = _r.velocity;
			}
		}

		private void OnCollisionExit(Collision c)
		{
			if (!(SoundMaterial == null) && base.enabled && SoundMaterial.AudioSets.Count != 0 && _audioContainersDic != null)
			{
				setSlideTargetVolumes(c.collider.gameObject, c.relativeVelocity, Vector3.up, base.transform.position, exit: true);
				_setPrevVelocity = true;
			}
		}

		private void OnTriggerEnter(Collider c)
		{
			if (!(SoundMaterial == null) && base.enabled && SoundMaterial.AudioSets.Count != 0)
			{
				playImpactSound(c.gameObject, TotalKinematicVelocity, Vector3.zero, c.transform.position);
			}
		}

		private void OnTriggerStay(Collider c)
		{
			if (!(SoundMaterial == null) && base.enabled && SoundMaterial.AudioSets.Count != 0 && _audioContainersDic != null)
			{
				setSlideTargetVolumes(c.gameObject, TotalKinematicVelocity, Vector3.zero, c.transform.position, exit: false);
			}
		}

		private void OnTriggerExit(Collider c)
		{
			if (!(SoundMaterial == null) && base.enabled && SoundMaterial.AudioSets.Count != 0 && _audioContainersDic != null)
			{
				setSlideTargetVolumes(c.gameObject, TotalKinematicVelocity, Vector3.zero, c.transform.position, exit: true);
			}
		}

		private void OnCollisionEnter2D(Collision2D c)
		{
			if (!(SoundMaterial == null) && base.enabled && SoundMaterial.AudioSets.Count != 0)
			{
				playImpactSound(c.collider.gameObject, c.relativeVelocity, c.contacts[0].normal, c.contacts[0].point);
				_setPrevVelocity = true;
			}
		}

		private void OnCollisionStay2D(Collision2D c)
		{
			if (!(SoundMaterial == null) && base.enabled && SoundMaterial.AudioSets.Count != 0 && _audioContainersDic != null)
			{
				if (_setPrevVelocity)
				{
					_prevVelocity = _r2D.velocity;
					_setPrevVelocity = false;
				}
				Vector3 relativeVelocity = _r2D.velocity - (Vector2)_prevVelocity;
				playImpactSound(c.collider.gameObject, relativeVelocity, c.contacts[0].normal, c.contacts[0].point);
				setSlideTargetVolumes(c.collider.gameObject, c.relativeVelocity, c.contacts[0].normal, c.contacts[0].point, exit: false);
				_prevVelocity = _r2D.velocity;
			}
		}

		private void OnCollisionExit2D(Collision2D c)
		{
			if (!(SoundMaterial == null) && base.enabled && SoundMaterial.AudioSets.Count != 0 && _audioContainersDic != null)
			{
				setSlideTargetVolumes(c.collider.gameObject, c.relativeVelocity, Vector3.up, base.transform.position, exit: true);
				_setPrevVelocity = true;
			}
		}

		private void OnTriggerEnter2D(Collider2D c)
		{
			if (!(SoundMaterial == null) && base.enabled && SoundMaterial.AudioSets.Count != 0)
			{
				playImpactSound(c.gameObject, TotalKinematicVelocity, Vector3.zero, c.transform.position);
			}
		}

		private void OnTriggerStay2D(Collider2D c)
		{
			if (!(SoundMaterial == null) && base.enabled && SoundMaterial.AudioSets.Count != 0 && _audioContainersDic != null)
			{
				setSlideTargetVolumes(c.gameObject, TotalKinematicVelocity, Vector3.zero, c.transform.position, exit: false);
			}
		}

		private void OnTriggerExit2D(Collider2D c)
		{
			if (!(SoundMaterial == null) && base.enabled && SoundMaterial.AudioSets.Count != 0 && _audioContainersDic != null)
			{
				setSlideTargetVolumes(c.gameObject, TotalKinematicVelocity, Vector3.zero, c.transform.position, exit: true);
			}
		}

		public bool HasAudioContainer(int keyIndex)
		{
			foreach (PhysSoundAudioContainer audioContainer in AudioContainers)
			{
				if (audioContainer.CompareKeyIndex(keyIndex))
				{
					return true;
				}
			}
			return false;
		}

		public void AddAudioContainer(int keyIndex)
		{
			AudioContainers.Add(new PhysSoundAudioContainer(keyIndex));
		}

		public void RemoveAudioContainer(int keyIndex)
		{
			int num = 0;
			while (true)
			{
				if (num < AudioContainers.Count)
				{
					if (AudioContainers[num].KeyIndex == keyIndex)
					{
						break;
					}
					num++;
					continue;
				}
				return;
			}
			AudioContainers.RemoveAt(num);
		}
	}
}
